package zero_trust_dlp_custom_profile_test

import (
	"fmt"
	"os"
	"regexp"
	"testing"

	"github.com/hashicorp/terraform-plugin-testing/helper/resource"
	"github.com/hashicorp/terraform-plugin-testing/knownvalue"
	"github.com/hashicorp/terraform-plugin-testing/statecheck"
	"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"

	"github.com/cloudflare/terraform-provider-cloudflare/internal/acctest"
	"github.com/cloudflare/terraform-provider-cloudflare/internal/utils"
)

// TestMigrateZeroTrustDLPCustomProfile_V4ToV5_BasicProfile tests migration of a simple DLP profile from v4 to v5
func TestMigrateZeroTrustDLPCustomProfile_V4ToV5_BasicProfile(t *testing.T) {
	rnd := utils.GenerateRandomResourceName()
	resourceName := "cloudflare_dlp_profile." + rnd
	tmpDir := t.TempDir()
	accountID := os.Getenv("CLOUDFLARE_ACCOUNT_ID")

	// Create v4 configuration with single entry block
	v4Config := fmt.Sprintf(`
resource "cloudflare_dlp_profile" "%[1]s" {
  account_id          = "%[2]s"
  name                = "test-dlp-%[1]s"
  description         = "Test DLP profile"
  type                = "custom"
  allowed_match_count = 5

  entry {
    name    = "Test CC %[1]s"
    enabled = true
    pattern {
      regex      = "4[0-9]{12}(?:[0-9]{3})?"
      validation = "luhn"
    }
  }
}`, rnd, accountID)

	resource.Test(t, resource.TestCase{
		PreCheck: func() {
			acctest.TestAccPreCheck(t)
			acctest.TestAccPreCheck_AccountID(t)
		},
		WorkingDir: tmpDir,
		Steps: []resource.TestStep{
			{
				// Step 1: Create with v4 provider
				ExternalProviders: map[string]resource.ExternalProvider{
					"cloudflare": {
						Source:            "cloudflare/cloudflare",
						VersionConstraint: "4.52.1",
					},
				},
				Config: v4Config,
				Check: resource.ComposeTestCheckFunc(
					resource.TestCheckResourceAttr(resourceName, "type", "custom"),
					resource.TestCheckResourceAttr(resourceName, "allowed_match_count", "5"),
					// ID is auto-generated by API
					resource.TestCheckResourceAttrSet(resourceName, "entry.0.id"),
					resource.TestCheckResourceAttr(resourceName, "entry.0.name", "Test CC "+rnd),
				),
			},
			// Step 2: Run migration and verify state
			acctest.MigrationV2TestStep(t, v4Config, tmpDir, "4.52.1", "v4", "v5", []statecheck.StateCheck{
				statecheck.ExpectKnownValue(
					"cloudflare_zero_trust_dlp_custom_profile."+rnd,
					tfjsonpath.New("account_id"),
					knownvalue.StringExact(accountID),
				),
				statecheck.ExpectKnownValue(
					"cloudflare_zero_trust_dlp_custom_profile."+rnd,
					tfjsonpath.New("name"),
					knownvalue.StringRegexp(regexp.MustCompile(".*-"+rnd+"$")),
				),
				statecheck.ExpectKnownValue(
					"cloudflare_zero_trust_dlp_custom_profile."+rnd,
					tfjsonpath.New("allowed_match_count"),
					knownvalue.Float64Exact(5),
				),
				statecheck.ExpectKnownValue(
					"cloudflare_zero_trust_dlp_custom_profile."+rnd,
					tfjsonpath.New("entries"),
					knownvalue.ListSizeExact(1),
				),
			}),
		},
	})
}

// TestMigrateZeroTrustDLPCustomProfile_V4ToV5_MultipleEntries tests migration with multiple entries
func TestMigrateZeroTrustDLPCustomProfile_V4ToV5_MultipleEntries(t *testing.T) {
	rnd := utils.GenerateRandomResourceName()
	resourceName := "cloudflare_dlp_profile." + rnd
	tmpDir := t.TempDir()
	accountID := os.Getenv("CLOUDFLARE_ACCOUNT_ID")

	// Create v4 configuration with multiple entry blocks
	v4Config := fmt.Sprintf(`
resource "cloudflare_dlp_profile" "%[1]s" {
  account_id          = "%[2]s"
  name                = "multi-pattern-%[1]s"
  type                = "custom"
  allowed_match_count = 10

  entry {
    name    = "Visa %[1]s"
    enabled = true
    pattern {
      regex      = "4[0-9]{12}(?:[0-9]{3})?"
      validation = "luhn"
    }
  }

  entry {
    name    = "MC %[1]s"
    enabled = true
    pattern {
      regex      = "5[1-5][0-9]{14}"
      validation = "luhn"
    }
  }

  entry {
    name    = "SSN %[1]s"
    enabled = false
    pattern {
      regex = "[0-9]{3}-[0-9]{2}-[0-9]{4}"
    }
  }
}`, rnd, accountID)

	resource.Test(t, resource.TestCase{
		PreCheck: func() {
			acctest.TestAccPreCheck(t)
			acctest.TestAccPreCheck_AccountID(t)
		},
		WorkingDir: tmpDir,
		Steps: []resource.TestStep{
			{
				// Step 1: Create with v4 provider
				ExternalProviders: map[string]resource.ExternalProvider{
					"cloudflare": {
						Source:            "cloudflare/cloudflare",
						VersionConstraint: "4.52.1",
					},
				},
				Config: v4Config,
				Check: resource.ComposeTestCheckFunc(
					resource.TestCheckResourceAttr(resourceName, "entry.#", "3"),
					// IDs are auto-generated, order may vary
					resource.TestCheckResourceAttrSet(resourceName, "entry.0.id"),
					resource.TestCheckResourceAttrSet(resourceName, "entry.1.id"),
					resource.TestCheckResourceAttrSet(resourceName, "entry.2.id"),
				),
			},
			// Step 2: Run migration and verify state
			acctest.MigrationV2TestStep(t, v4Config, tmpDir, "4.52.1", "v4", "v5", []statecheck.StateCheck{
				statecheck.ExpectKnownValue(
					"cloudflare_zero_trust_dlp_custom_profile."+rnd,
					tfjsonpath.New("account_id"),
					knownvalue.StringExact(accountID),
				),
				statecheck.ExpectKnownValue(
					"cloudflare_zero_trust_dlp_custom_profile."+rnd,
					tfjsonpath.New("name"),
					knownvalue.StringExact("multi-pattern-"+rnd),
				),
				statecheck.ExpectKnownValue(
					"cloudflare_zero_trust_dlp_custom_profile."+rnd,
					tfjsonpath.New("allowed_match_count"),
					knownvalue.Float64Exact(10),
				),
				statecheck.ExpectKnownValue(
					"cloudflare_zero_trust_dlp_custom_profile."+rnd,
					tfjsonpath.New("entries"),
					knownvalue.ListSizeExact(3),
				),
			}),
		},
	})
}

// TestMigrateZeroTrustDLPCustomProfile_V4ToV5_MinimalProfile tests migration with minimal config
func TestMigrateZeroTrustDLPCustomProfile_V4ToV5_MinimalProfile(t *testing.T) {
	rnd := utils.GenerateRandomResourceName()
	//resourceName := "cloudflare_dlp_profile." + rnd
	tmpDir := t.TempDir()
	accountID := os.Getenv("CLOUDFLARE_ACCOUNT_ID")

	// Create minimal v4 configuration
	v4Config := fmt.Sprintf(`
resource "cloudflare_dlp_profile" "%[1]s" {
  account_id          = "%[2]s"
  name                = "minimal-%[1]s"
  type                = "custom"
  allowed_match_count = 1

  entry {
    name    = "Simple %[1]s"
    enabled = true
    pattern {
      regex = "test[0-9]{3,5}"
    }
  }
}`, rnd, accountID)

	resource.Test(t, resource.TestCase{
		PreCheck: func() {
			acctest.TestAccPreCheck(t)
			acctest.TestAccPreCheck_AccountID(t)
		},
		WorkingDir: tmpDir,
		Steps: []resource.TestStep{
			{
				// Step 1: Create with v4 provider
				ExternalProviders: map[string]resource.ExternalProvider{
					"cloudflare": {
						Source:            "cloudflare/cloudflare",
						VersionConstraint: "4.52.1",
					},
				},
				Config: v4Config,
			},
			// Step 2: Run migration and verify state
			acctest.MigrationV2TestStep(t, v4Config, tmpDir, "4.52.1", "v4", "v5", []statecheck.StateCheck{
				statecheck.ExpectKnownValue(
					"cloudflare_zero_trust_dlp_custom_profile."+rnd,
					tfjsonpath.New("account_id"),
					knownvalue.StringExact(accountID),
				),
				statecheck.ExpectKnownValue(
					"cloudflare_zero_trust_dlp_custom_profile."+rnd,
					tfjsonpath.New("name"),
					knownvalue.StringExact("minimal-"+rnd),
				),
				statecheck.ExpectKnownValue(
					"cloudflare_zero_trust_dlp_custom_profile."+rnd,
					tfjsonpath.New("allowed_match_count"),
					knownvalue.Float64Exact(1),
				),
				statecheck.ExpectKnownValue(
					"cloudflare_zero_trust_dlp_custom_profile."+rnd,
					tfjsonpath.New("entries"),
					knownvalue.ListSizeExact(1),
				),
			}),
		},
	})
}

// TestMigrateZeroTrustDLPCustomProfile_V4ToV5_ComplexPatterns tests migration with complex validation patterns
func TestMigrateZeroTrustDLPCustomProfile_V4ToV5_ComplexPatterns(t *testing.T) {
	rnd := utils.GenerateRandomResourceName()
	resourceName := "cloudflare_dlp_profile." + rnd
	tmpDir := t.TempDir()
	accountID := os.Getenv("CLOUDFLARE_ACCOUNT_ID")

	// Create v4 configuration with complex patterns
	v4Config := fmt.Sprintf(`
resource "cloudflare_dlp_profile" "%[1]s" {
  account_id          = "%[2]s"
  name                = "complex-%[1]s"
  description         = "Complex pattern detection"
  type                = "custom"
  allowed_match_count = 3

  entry {
    name    = "Luhn %[1]s"
    enabled = true
    pattern {
      regex      = "3[47][0-9]{13}"
      validation = "luhn"
    }
  }

  entry {
    name    = "NoVal %[1]s"
    enabled = false
    pattern {
      regex = "[A-Z]{2}[0-9]{6}"
    }
  }
}`, rnd, accountID)

	resource.Test(t, resource.TestCase{
		PreCheck: func() {
			acctest.TestAccPreCheck(t)
			acctest.TestAccPreCheck_AccountID(t)
		},
		WorkingDir: tmpDir,
		Steps: []resource.TestStep{
			{
				// Step 1: Create with v4 provider
				ExternalProviders: map[string]resource.ExternalProvider{
					"cloudflare": {
						Source:            "cloudflare/cloudflare",
						VersionConstraint: "4.52.1",
					},
				},
				Config: v4Config,
				Check: resource.ComposeTestCheckFunc(
					// Just check that we have 2 entries, order may vary
					resource.TestCheckResourceAttr(resourceName, "entry.#", "2"),
					resource.TestCheckResourceAttrSet(resourceName, "entry.0.id"),
					resource.TestCheckResourceAttrSet(resourceName, "entry.1.id"),
				),
			},
			// Step 2: Run migration and verify state
			acctest.MigrationV2TestStep(t, v4Config, tmpDir, "4.52.1", "v4", "v5", []statecheck.StateCheck{
				statecheck.ExpectKnownValue(
					"cloudflare_zero_trust_dlp_custom_profile."+rnd,
					tfjsonpath.New("account_id"),
					knownvalue.StringExact(accountID),
				),
				statecheck.ExpectKnownValue(
					"cloudflare_zero_trust_dlp_custom_profile."+rnd,
					tfjsonpath.New("name"),
					knownvalue.StringExact("complex-"+rnd),
				),
				statecheck.ExpectKnownValue(
					"cloudflare_zero_trust_dlp_custom_profile."+rnd,
					tfjsonpath.New("allowed_match_count"),
					knownvalue.Float64Exact(3),
				),
				statecheck.ExpectKnownValue(
					"cloudflare_zero_trust_dlp_custom_profile."+rnd,
					tfjsonpath.New("entries"),
					knownvalue.ListSizeExact(2),
				),
			}),
		},
	})
}

// TestMigrateZeroTrustDLPCustomProfile_V4ToV5_NoDescription tests migration without description field
func TestMigrateZeroTrustDLPCustomProfile_V4ToV5_NoDescription(t *testing.T) {
	rnd := utils.GenerateRandomResourceName()
	//resourceName := "cloudflare_dlp_profile." + rnd
	tmpDir := t.TempDir()
	accountID := os.Getenv("CLOUDFLARE_ACCOUNT_ID")

	// Create v4 configuration without description
	v4Config := fmt.Sprintf(`
resource "cloudflare_dlp_profile" "%[1]s" {
  account_id          = "%[2]s"
  name                = "no-desc-%[1]s"
  type                = "custom"
  allowed_match_count = 0

  entry {
    name    = "Test %[1]s"
    enabled = false
    pattern {
      regex = "test[0-9]{3}"
    }
  }
}`, rnd, accountID)

	resource.Test(t, resource.TestCase{
		PreCheck: func() {
			acctest.TestAccPreCheck(t)
			acctest.TestAccPreCheck_AccountID(t)
		},
		WorkingDir: tmpDir,
		Steps: []resource.TestStep{
			{
				// Step 1: Create with v4 provider
				ExternalProviders: map[string]resource.ExternalProvider{
					"cloudflare": {
						Source:            "cloudflare/cloudflare",
						VersionConstraint: "4.52.1",
					},
				},
				Config: v4Config,
			},
			// Step 2: Run migration and verify state
			acctest.MigrationV2TestStep(t, v4Config, tmpDir, "4.52.1", "v4", "v5", []statecheck.StateCheck{
				statecheck.ExpectKnownValue(
					"cloudflare_zero_trust_dlp_custom_profile."+rnd,
					tfjsonpath.New("allowed_match_count"),
					knownvalue.Int64Exact(0),
				),
				statecheck.ExpectKnownValue(
					"cloudflare_zero_trust_dlp_custom_profile."+rnd,
					tfjsonpath.New("entries").AtSliceIndex(0).AtMapKey("enabled"),
					knownvalue.Bool(false),
				),
			}),
		},
	})
}
